import { Controller, Get } from '@nestjs/common'
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'
import { HealthCheckService, HealthCheck, MemoryHealthIndicator, DiskHealthIndicator } from '@nestjs/terminus'
import { ConfigService } from '@nestjs/config'
import { RedisService } from '@liaoliaots/nestjs-redis'
import { Redis } from 'ioredis'
import { DatabaseService } from '../database/database.service'
import { HealthCheckDto } from '../common/dto/system.dto'

/**
 * 健康检查控制器
 * 提供系统各组件的健康状态检查
 */
@ApiTags('系统管理')
@Controller('health')
export class HealthController {
  private redis: Redis

  constructor(
    private health: HealthCheckService,
    private databaseService: DatabaseService,
    private memory: MemoryHealthIndicator,
    private disk: DiskHealthIndicator,
    private configService: ConfigService,
    private redisService: RedisService
  ) {
    this.redis = this.redisService.getOrThrow()
  }

  /**
   * 基础健康检查
   * 快速检查服务是否正常运行
   */
  @Get()
  @ApiOperation({
    summary: '基础健康检查',
    description: '快速检查服务是否正常运行，返回基本状态信息'
  })
  @ApiResponse({
    status: 200,
    description: '服务正常',
    type: HealthCheckDto
  })
  @ApiResponse({
    status: 503,
    description: '服务异常'
  })
  async check() {
    return {
      status: 'ok',
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      environment: this.configService.get('NODE_ENV'),
      version: process.env.npm_package_version || '1.0.0',
      node_version: process.version,
      memory: {
        used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
        total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
        external: Math.round(process.memoryUsage().external / 1024 / 1024)
      }
    }
  }

  /**
   * 详细健康检查
   * 检查所有依赖服务的健康状态
   */
  @Get('detailed')
  @ApiOperation({
    summary: '详细健康检查',
    description: '检查数据库、Redis、内存、磁盘等所有依赖服务的健康状态'
  })
  @ApiResponse({
    status: 200,
    description: '所有服务正常'
  })
  @ApiResponse({
    status: 503,
    description: '部分或全部服务异常'
  })
  @HealthCheck()
  async checkDetailed() {
    return this.health.check([
      // 数据库健康检查
      async () => {
        try {
          const isHealthy = await this.databaseService.healthCheck()
          if (isHealthy) {
            return {
              database: {
                status: 'up',
                message: 'Database is responding'
              }
            }
          }
          throw new Error('Database health check failed')
        } catch (error) {
          return {
            database: {
              status: 'down',
              message: error.message
            }
          }
        }
      },

      // Redis健康检查
      async () => {
        try {
          const result = await this.redis.ping()
          if (result === 'PONG') {
            return {
              redis: {
                status: 'up',
                message: 'Redis is responding'
              }
            }
          }
          throw new Error('Redis ping failed')
        } catch (error) {
          return {
            redis: {
              status: 'down',
              message: error.message
            }
          }
        }
      },

      // 内存使用检查（警告阈值：1GB，错误阈值：1.5GB）
      () => this.memory.checkHeap('memory_heap', 1024 * 1024 * 1024),
      () => this.memory.checkRSS('memory_rss', 1536 * 1024 * 1024),

      // 磁盘空间检查（警告阈值：80%，错误阈值：90%）
      () =>
        this.disk.checkStorage('storage', {
          path: '/',
          thresholdPercent: 0.9
        })
    ])
  }

  /**
   * 就绪检查
   * 检查应用是否准备好接收流量
   */
  @Get('ready')
  @ApiOperation({
    summary: '就绪检查',
    description: '检查应用是否准备好接收流量，主要用于Kubernetes就绪探针'
  })
  @ApiResponse({
    status: 200,
    description: '应用已就绪'
  })
  @ApiResponse({
    status: 503,
    description: '应用未就绪'
  })
  @HealthCheck()
  async checkReadiness() {
    return this.health.check([
      // 检查数据库连接
      async () => {
        try {
          const isHealthy = await this.databaseService.healthCheck()
          if (!isHealthy) {
            throw new Error('Database connection failed')
          }
          return {
            database: {
              status: 'up'
            }
          }
        } catch (error) {
          throw new Error(`Database connection failed: ${error.message}`)
        }
      },

      // 检查Redis连接
      async () => {
        try {
          await this.redis.ping()
          return {
            redis: {
              status: 'up'
            }
          }
        } catch (error) {
          throw new Error(`Redis connection failed: ${error.message}`)
        }
      }
    ])
  }

  /**
   * 存活检查
   * 检查应用进程是否存活
   */
  @Get('live')
  @ApiOperation({
    summary: '存活检查',
    description: '检查应用进程是否存活，主要用于Kubernetes存活探针'
  })
  @ApiResponse({
    status: 200,
    description: '应用存活'
  })
  async checkLiveness() {
    return {
      status: 'ok',
      timestamp: new Date().toISOString(),
      pid: process.pid,
      uptime: process.uptime()
    }
  }

  /**
   * 系统信息
   * 获取详细的系统运行信息
   */
  @Get('info')
  @ApiOperation({
    summary: '系统信息',
    description: '获取详细的系统运行信息，包括环境变量、配置等'
  })
  @ApiResponse({
    status: 200,
    description: '系统信息获取成功'
  })
  async getSystemInfo() {
    const memoryUsage = process.memoryUsage()
    const cpuUsage = process.cpuUsage()

    return {
      application: {
        name: process.env.npm_package_name || 'cms-api',
        version: process.env.npm_package_version || '1.0.0',
        environment: this.configService.get('NODE_ENV'),
        port: this.configService.get('PORT'),
        timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
      },
      system: {
        platform: process.platform,
        arch: process.arch,
        node_version: process.version,
        pid: process.pid,
        uptime: process.uptime(),
        started_at: new Date(Date.now() - process.uptime() * 1000).toISOString()
      },
      memory: {
        heap_used: Math.round(memoryUsage.heapUsed / 1024 / 1024),
        heap_total: Math.round(memoryUsage.heapTotal / 1024 / 1024),
        external: Math.round(memoryUsage.external / 1024 / 1024),
        array_buffers: Math.round(memoryUsage.arrayBuffers / 1024 / 1024),
        rss: Math.round(memoryUsage.rss / 1024 / 1024)
      },
      cpu: {
        user: cpuUsage.user,
        system: cpuUsage.system
      },
      database: {
        type: this.configService.get('database.type'),
        host: this.configService.get('database.host'),
        port: this.configService.get('database.port'),
        database: this.configService.get('database.database')
      },
      redis: {
        host: this.configService.get('redis.host'),
        port: this.configService.get('redis.port'),
        db: this.configService.get('redis.db')
      }
    }
  }

  /**
   * 性能指标
   * 获取应用性能相关指标
   */
  @Get('metrics')
  @ApiOperation({
    summary: '性能指标',
    description: '获取应用性能相关指标，用于监控和告警'
  })
  @ApiResponse({
    status: 200,
    description: '性能指标获取成功'
  })
  async getMetrics() {
    const memoryUsage = process.memoryUsage()
    const cpuUsage = process.cpuUsage()

    // 获取事件循环延迟（简单实现）
    const start = process.hrtime.bigint()
    await new Promise(resolve => setImmediate(resolve))
    const eventLoopDelay = Number(process.hrtime.bigint() - start) / 1000000 // 转换为毫秒

    return {
      timestamp: new Date().toISOString(),
      uptime_seconds: process.uptime(),
      memory: {
        heap_used_bytes: memoryUsage.heapUsed,
        heap_total_bytes: memoryUsage.heapTotal,
        external_bytes: memoryUsage.external,
        rss_bytes: memoryUsage.rss,
        heap_usage_percent: (memoryUsage.heapUsed / memoryUsage.heapTotal) * 100
      },
      cpu: {
        user_microseconds: cpuUsage.user,
        system_microseconds: cpuUsage.system,
        total_microseconds: cpuUsage.user + cpuUsage.system
      },
      event_loop: {
        delay_milliseconds: eventLoopDelay
      },
      process: {
        pid: process.pid,
        ppid: process.ppid,
        platform: process.platform,
        arch: process.arch,
        node_version: process.version
      }
    }
  }
}
